﻿using GalaSoft.MvvmLight;
using System.Linq;
using System.Collections.ObjectModel;
using JiveMessenger.Models;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
using JiveMessenger.User;
using GalaSoft.MvvmLight.Ioc;
using JiveMessenger.Utilities;
using Windows.UI.Xaml.Media.Imaging;
using JmShared;
using Windows.Storage;
using JiveMessenger.Log;
namespace JiveMessenger.ViewModels
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class ViewModelGetUserEmoticons : ViewModelBaseEx
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private IClient _currentClient;
        public RelayCommand AddEmoticonsCommand { get; set; }
        public RelayCommand<AddUserEmoticonModel> ShortcutChangedCommand { get; set; }
        public RelayCommand<bool> CheckUncheckAllCommand { get; set; }
        //public ObservableCollection<string> ClientList { get; set; }

        private ObservableCollection<AddUserEmoticonModel> _emoticonList;
        public ObservableCollection<AddUserEmoticonModel> EmoticonList
        {
            get { return _emoticonList; }
            set
            {
                if (_emoticonList != value)
                {
                    if (_emoticonList != null)
                        _emoticonList.CollectionChanged -= _emoticonList_CollectionChanged;
                    Set(() => EmoticonList, ref _emoticonList, value);
                    if (_emoticonList != null)
                        _emoticonList.CollectionChanged += _emoticonList_CollectionChanged;
                }
            }
        }

        void _emoticonList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (AddUserEmoticonModel model in e.NewItems)
                    model.PropertyChanged += ViewModelGetUserEmoticons_PropertyChanged;
            }
            if (e.OldItems != null)
            {
                foreach (AddUserEmoticonModel model in e.OldItems)
                    model.PropertyChanged -= ViewModelGetUserEmoticons_PropertyChanged;
            }
        }

        void ViewModelGetUserEmoticons_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "EmoticonShortcut")
            {
                ShortcutChangedCommand.Execute(sender as AddUserEmoticonModel);
            }
            else if (e.PropertyName == "ErrorText")
            {
                var model = sender as AddUserEmoticonModel;
                if (string.IsNullOrEmpty(model.ErrorText) && model.EmoticonFileExists)
                    model.ErrorText = "You already have this emoticon image";
            }
        }



        private bool _isAddButtonEnabled;
        public bool IsAddButtonEnabled
        {
            get { return _isAddButtonEnabled; }
            set
            {
                if (_isAddButtonEnabled != value)
                {
                    Set(() => IsAddButtonEnabled, ref _isAddButtonEnabled, value);
                }
            }
        }

        private IContact _selectedUser;
        public IContact SelectedUser
        {
            get { return _selectedUser; }
            set
            {
                if (_selectedUser != value)
                {
                    Set(() => SelectedUser, ref _selectedUser, value);
                    CreateEmoticonListForUser(_selectedUser);
                }
            }
        }

        private bool _showProgressOverlay;
        public bool ShowProgressOverlay
        {
            get { return _showProgressOverlay; }
            set
            {
                if (_showProgressOverlay != value)
                {
                    Set(() => ShowProgressOverlay, ref _showProgressOverlay, value);
                }
            }
        }

        private double _progressValue;
        public double ProgressValue
        {
            get { return _progressValue; }
            set
            {
                if (_progressValue != value)
                {
                    Set(() => ProgressValue, ref _progressValue, value);
                }
            }
        }


        /// <summary>
        /// Initializes a new instance of the ViewModelGetUserEmoticons class.
        /// </summary>
        public ViewModelGetUserEmoticons(IClient currentClient, IContact selectedUser)
        {
            _currentClient = currentClient;
            IsAddButtonEnabled = false;
            EmoticonList = new ObservableCollection<AddUserEmoticonModel>();
            //ClientList = new ObservableCollection<string>();
            AddEmoticonsCommand = new RelayCommand(AddEmoticonsCommandAction);
            ShortcutChangedCommand = new RelayCommand<AddUserEmoticonModel>(ShortcutChangedCommandAction);
            CheckUncheckAllCommand = new RelayCommand<bool>(CheckUncheckAllCommandAction);
            //foreach (string userID in currentClient.ConnectedClients.Keys)
            //    ClientList.Add(userID);

            //if (ClientList.Count > 0)
            //  SelectedUserID = ClientList.First();
            this.SelectedUser = selectedUser;
        }

        //public override void Cleanup()
        //{
        //    SimpleIoc.Default.Unregister<ViewModelGetUserEmoticons>(VmHelper.Locator.ViewModelGetUserEmoticonsKey);
        //    VmHelper.Locator.ViewModelGetUserEmoticonsKey = System.Guid.NewGuid().ToString();
        //    base.Cleanup();
        //}

        private void ShortcutChangedCommandAction(AddUserEmoticonModel model)
        {

            string error;
            model.IsValidShortcut = _currentClient.ValidateEmoticonShortcut((string)model.EmoticonShortcut, out error);
            model.ErrorText = error;
        }
        private void CheckUncheckAllCommandAction(bool ischecked)
        {
            foreach (AddUserEmoticonModel model in this.EmoticonList)
            {
                model.IsChecked = ischecked;
            }

        }
        private void CreateEmoticonListForUser(IContact user)
        {
            EmoticonList.Clear();
            IsAddButtonEnabled = false;

            foreach (KeyValuePair<string, IEmoticon> kvp in _currentClient.GetEmoticons(user.UserID, false, true, false))
            {
                string error;
                bool isValidShortcut = _currentClient.ValidateEmoticonShortcut(kvp.Key, out error);
                bool emoticonExists = ValidateEmoticonExistsByHash(kvp.Value);
                if (emoticonExists)
                    error = "You already have this emoticon image";

                var model = new AddUserEmoticonModel()
                {
                    EmoticonShortcut = kvp.Key,
                    EmoticonPath = kvp.Value.EmoticonPath,
                    IsValidShortcut = isValidShortcut,
                    EmoticonFileExists = emoticonExists,
                    ErrorText = error,
                    IsChecked = true
                };

                EmoticonList.Add(model);
            }
            if (EmoticonList.Count > 0)
                IsAddButtonEnabled = true;
        }
        /// <summary>
        /// Checks if the hash of the emoticon matches any of the current clients emoticons
        /// </summary>
        /// <param name="emoticon"></param>
        /// <returns>Returns true if the user have the emoticon, else false</returns>
        private bool ValidateEmoticonExistsByHash(IEmoticon emoticon)
        {
            try
            {
                string hash = Path.GetFileNameWithoutExtension(emoticon.EmoticonPath);
                if (this._currentClient.CurrentUserInfo.CustomEmoticons.Any(x => x.Hash == hash))
                    return true;
                else
                    return false;
                //using (Stream stream = File.Open(emoticon.EmoticonPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                //{
                //    using (MD5 md5 = MD5.Create())
                //    {
                //        var hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
                //        stream.Close();
                //        if (this._currentClient.CurrentUserInfo.CustomEmoticons.Any(x => x.Hash == hash))
                //            return true;
                //        else
                //            return false;
                //    }
                //}

            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error checking if emoticon file exists by hash", ex);
                throw;
            }
        }
        private async void AddEmoticonsCommandAction()
        {
            if (this.EmoticonList.Count == 0)
                return;

            try
            {
                ShowProgressOverlay = true;
                int addedCount = 0;
                int errorCount = 0;
                foreach (AddUserEmoticonModel model in this.EmoticonList.Where(x => x.CanAddEmoticon && x.IsChecked))
                {
                    try
                    {
                        StorageFolder folder = await StaticMethods.GetEmoticonStorageFolderForUser(_currentClient.CurrentUserInfo.UserName);
                        StorageFile sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(model.EmoticonPath));
                        StorageFile newFile = await sourceFile.CopyAsync(folder, sourceFile.Name, NameCollisionOption.ReplaceExisting);
                        //byte[] img = await StaticMethods.LoadImageData(sourceFile);
                        //string hash = await StaticMethods.ComputeMD5Async(img);
                        //StorageFile file = await StaticMethods.SaveImageToStorage(folder,img, Path.GetFileName(model.EmoticonPath));
                        //string savePath = file.Path;
                        //model.EmoticonPath = savePath;
                        string hash = Path.GetFileNameWithoutExtension(newFile.Path);
                        string extension = Path.GetExtension(newFile.Path);
                        ContactEmoticon ce = new ContactEmoticon()
                        {
                            Keyword = model.EmoticonShortcut,
                            Hash = hash,
                            Extension = extension
                        };
                        this._currentClient.UserSettings.CustomEmoticons.Add(ce);
                        this._currentClient.CurrentUserInfo.CustomEmoticons.Add(ce);
                        //  string error;
                        //  model.IsValidShortcut = _currentClient.ValidateEmoticonShortcut((string)model.EmoticonShortcut, out error);
                        //  model.ErrorText = error;
                        addedCount++;

                    }
                    catch (Exception err)
                    {
                        Logger.ErrorException("Error adding emoticon", err);
                        errorCount++;
                    }
                    ProgressValue = addedCount + errorCount;
                }
                if (addedCount > 0 || errorCount > 0)
                {
                    if (errorCount == 0)
                        Messenger.Default.Send(new JiveToastMessage(string.Format("Added {0} new emoticons", addedCount)));
                    else
                        Messenger.Default.Send(new JiveToastMessage(string.Format("Added {0} new emoticons. {1} emoticons could not be copied.", addedCount, errorCount)));
                }

                if (addedCount > 0)
                {
                    Messenger.Default.Send(new NotificationMessage(this, "UpdateCustomEmoticons"));
                    WpUserSettings settings = new WpUserSettings();
                    settings.CustomEmoticons = _currentClient.CurrentUserInfo.CustomEmoticons;
                   await  _currentClient.Connection.SendCommand(settings, ClientCommands.WpSettings);

                    foreach (var model in this.EmoticonList)
                    {
                        ShortcutChangedCommand.Execute(model);
                    }
                }
            }
            finally
            {
                ShowProgressOverlay = false;
                ProgressValue = 0;
            }

        }

    }
}